"""
Tushare数据源适配器 (V2重构版)
==============================

完全基于配置注入的Tushare适配器，符合RedFire V2架构规范。

核心改进:
- 完全依赖配置注入，不直接访问全局配置
- 继承HistoricalDataAdapter标准接口
- 使用asyncio.to_thread避免阻塞事件循环
- 清晰的错误处理和异常映射
- 支持可选的缓存管理器注入

作者: 架构组
创建日期: 2025-10-05
"""

import asyncio
import logging
import time
from typing import List, Optional, Dict, Any
from datetime import datetime
from dataclasses import dataclass
import pandas as pd

# 导入标准适配器接口和模型
from ...core import (
    HistoricalDataAdapter,
    Bar,
    Tick,
    DataFrequency,
    AdapterConnectionError,
    AdapterAuthenticationError,
    AdapterDataError,
    AdapterTimeoutError,
    AdapterRateLimitError,
    AdapterConfigError,
    # 能力声明相关（暂时注释掉，等待实现）
    # CapableAdapter,
    # AdapterCapability,
    # DataType,
    # MarketRegion,
    # AdapterFeature,
    # 元数据相关
    AdapterMetadata,
    create_tushare_metadata,
)

# 可选导入Tushare
try:
    import tushare as ts
    TUSHARE_AVAILABLE = True
except ImportError:
    TUSHARE_AVAILABLE = False
    logging.warning("Tushare包未安装，TushareAdapter将不可用")


@dataclass
class TushareAdapterConfig:
    """
    Tushare适配器配置
    
    所有配置都通过此类注入，不依赖全局配置系统
    """
    # 必需配置
    token: str                              # Tushare API Token
    
    # 可选配置
    enabled: bool = True                    # 是否启用
    timeout: int = 30                       # 请求超时时间（秒）
    retry_count: int = 3                    # 重试次数
    retry_delay: float = 1.0                # 重试延迟（秒）
    rate_limit_calls: int = 200             # 每分钟调用次数限制
    rate_limit_period: int = 60             # 限流周期（秒）
    
    # 数据配置
    default_fields: Optional[Dict[str, str]] = None  # 默认字段映射
    
    def __post_init__(self):
        """验证配置"""
        if not self.token:
            raise AdapterConfigError("Tushare token不能为空")
        if self.timeout <= 0:
            raise AdapterConfigError("timeout必须大于0")
        if self.retry_count < 0:
            raise AdapterConfigError("retry_count不能为负数")
    
    @classmethod
    def from_dict(cls, config: Dict[str, Any]) -> "TushareAdapterConfig":
        """从字典创建配置对象"""
        return cls(
            token=config.get("token", ""),
            enabled=config.get("enabled", True),
            timeout=config.get("timeout", 30),
            retry_count=config.get("retry_count", 3),
            retry_delay=config.get("retry_delay", 1.0),
            rate_limit_calls=config.get("rate_limit_calls", 200),
            rate_limit_period=config.get("rate_limit_period", 60),
            default_fields=config.get("default_fields"),
        )


class TushareAdapter(HistoricalDataAdapter):
    """
    Tushare历史数据适配器
    
    特性:
    - 完全基于配置注入
    - 异步执行，不阻塞事件循环
    - 标准化的错误处理
    - 支持多种数据频率
    - 可选的缓存支持
    - 能力声明支持（用于智能路由）
    
    使用示例:
        ```python
        # 创建配置
        config = TushareAdapterConfig(
            token="your_token_here",
            timeout=30,
            retry_count=3
        )
        
        # 创建适配器
        adapter = TushareAdapter(config)
        
        # 连接并查询数据
        async with adapter:
            bars = await adapter.query_bars(
                symbol="000001.SZ",
                start_time=datetime(2025, 1, 1),
                end_time=datetime(2025, 10, 4),
                frequency="1d"
            )
        
        # 获取能力声明
        capability = adapter.get_capability()
        print(f"支持的数据类型: {capability.supported_data_types}")
        ```
    """
    
    def __init__(
        self,
        config: TushareAdapterConfig,
        cache_manager: Optional[Any] = None,
        logger: Optional[logging.Logger] = None
    ):
        """
        初始化Tushare适配器
        
        Args:
            config: Tushare配置对象（必需）
            cache_manager: 可选的缓存管理器
            logger: 可选的日志记录器
        """
        self.config = config
        self.cache_manager = cache_manager
        self.logger = logger or logging.getLogger(__name__)
        
        # 运行时状态
        self._connected = False
        self._pro_api = None
        
        # 频率映射：标准频率 -> Tushare接口
        self._frequency_mapping = {
            DataFrequency.DAILY: "daily",
            DataFrequency.WEEKLY: "weekly",
            DataFrequency.MONTHLY: "monthly",
            # Tushare不直接支持分钟级数据，需要使用其他接口
        }
        
        self.logger.info(f"TushareAdapter初始化完成 (enabled={config.enabled})")
    
    # ==================== 生命周期方法 ====================
    
    async def initialize(self) -> None:
        """
        初始化适配器（由 AdapterManager 调用）
        
        自动连接到 Tushare
        """
        await self.connect()
    
    async def connect(self) -> None:
        """
        连接到Tushare数据源
        
        Raises:
            AdapterConnectionError: 如果Tushare包未安装
            AdapterAuthenticationError: 如果Token无效
            AdapterConfigError: 如果适配器未启用
        """
        if not TUSHARE_AVAILABLE:
            raise AdapterConnectionError(
                "Tushare包未安装，请运行: pip install tushare"
            )
        
        if not self.config.enabled:
            raise AdapterConfigError("Tushare适配器未启用")
        
        try:
            # 设置Token并创建Pro API
            ts.set_token(self.config.token)
            self._pro_api = ts.pro_api()
            
            # 测试连接
            await self._test_connection()
            
            self._connected = True
            self.logger.info("Tushare连接成功")
            
        except Exception as e:
            self._connected = False
            if "token" in str(e).lower() or "auth" in str(e).lower():
                raise AdapterAuthenticationError(f"Tushare认证失败: {e}")
            raise AdapterConnectionError(f"Tushare连接失败: {e}")
    
    async def disconnect(self) -> None:
        """断开连接"""
        self._pro_api = None
        self._connected = False
        self.logger.info("Tushare连接已断开")
    
    async def cleanup(self) -> None:
        """
        清理资源
        
        这是 disconnect() 的别名，用于统一服务生命周期管理接口
        """
        await self.disconnect()
    
    async def health_check(self) -> bool:
        """
        健康检查
        
        Returns:
            bool: True表示健康
        """
        if not self._connected or self._pro_api is None:
            return False
        
        try:
            # 简单的健康检查：获取今天的交易日历
            today = datetime.now().strftime('%Y%m%d')
            result = await self._execute_with_retry(
                lambda: self._pro_api.trade_cal(
                    exchange='SSE',
                    start_date=today,
                    end_date=today
                )
            )
            return result is not None and not result.empty
        except Exception as e:
            self.logger.warning(f"健康检查失败: {e}")
            return False
    
    async def _test_connection(self) -> None:
        """
        测试连接
        
        Raises:
            AdapterConnectionError: 连接测试失败
        """
        try:
            today = datetime.now().strftime('%Y%m%d')
            result = await self._execute_with_retry(
                lambda: self._pro_api.trade_cal(
                    exchange='SSE',
                    start_date=today,
                    end_date=today
                )
            )
            
            if result is None or result.empty:
                raise AdapterConnectionError("连接测试返回空数据")
                
        except Exception as e:
            raise AdapterConnectionError(f"连接测试失败: {e}")
    
    # ==================== 数据查询方法 ====================
    
    async def query_bars(
        self,
        symbol: str,
        start_time: datetime,
        end_time: datetime,
        frequency: str = "1d",
        **kwargs
    ) -> List[Bar]:
        """
        查询K线数据
        
        Args:
            symbol: 股票代码，格式如 '000001.SZ'
            start_time: 开始时间
            end_time: 结束时间
            frequency: 数据频率 ('1d', '1w', '1M')
            **kwargs: 额外参数
        
        Returns:
            List[Bar]: K线数据列表
        
        Raises:
            AdapterConnectionError: 未连接
            AdapterDataError: 数据获取失败
            NotImplementedError: 不支持的频率
        """
        if not self._connected:
            raise AdapterConnectionError("Tushare未连接")
        
        # 转换频率
        freq_enum = DataFrequency.from_string(frequency)
        if freq_enum not in self._frequency_mapping:
            raise NotImplementedError(f"Tushare不支持频率: {frequency}")
        
        tushare_freq = self._frequency_mapping[freq_enum]
        
        try:
            # 格式化日期
            start_date = start_time.strftime('%Y%m%d')
            end_date = end_time.strftime('%Y%m%d')
            
            # 查询数据
            df = await self._query_tushare_data(
                data_type=tushare_freq,
                ts_code=symbol,
                start_date=start_date,
                end_date=end_date
            )
            
            if df is None or df.empty:
                self.logger.warning(
                    f"未查询到数据: {symbol} {start_date}-{end_date}"
                )
                return []
            
            # 转换为Bar对象
            bars = self._convert_to_bars(df, symbol, frequency)
            
            self.logger.info(
                f"查询到{len(bars)}条K线: {symbol} {frequency} "
                f"{start_date}-{end_date}"
            )
            
            return bars
            
        except Exception as e:
            raise AdapterDataError(f"查询K线数据失败: {e}")
    
    async def query_ticks(
        self,
        symbol: str,
        start_time: datetime,
        end_time: datetime,
        **kwargs
    ) -> List[Tick]:
        """
        查询Tick数据
        
        Note: Tushare不直接支持Tick数据，此方法抛出NotImplementedError
        """
        raise NotImplementedError("Tushare不支持Tick数据查询")
    
    # ==================== 内部辅助方法 ====================
    
    async def _query_tushare_data(
        self,
        data_type: str,
        ts_code: str,
        start_date: str,
        end_date: str,
        fields: Optional[str] = None
    ) -> Optional[pd.DataFrame]:
        """
        查询Tushare数据的通用方法
        
        Args:
            data_type: 数据类型 ('daily', 'weekly', 'monthly')
            ts_code: 股票代码
            start_date: 开始日期 (YYYYMMDD)
            end_date: 结束日期 (YYYYMMDD)
            fields: 字段列表
        
        Returns:
            Optional[pd.DataFrame]: 查询结果
        """
        # 判断是否为指数代码（以 .SH 或 .SZ 结尾且代码以 0、3、8、9 开头的通常是指数）
        is_index = False
        if ts_code:
            code_prefix = ts_code.split('.')[0]
            # 000001.SH (上证指数), 399001.SZ (深证成指), HSI (恒生指数) 等
            # 注意：HSI在tushare中的代码可能是不同的格式
            if code_prefix.startswith(('000001', '399', '000300', '000016', '000905', '000852', 'HSI')):
                is_index = True
            # 特殊处理港股恒生指数
            if ts_code == 'HSI' or ts_code.startswith('HSI'):
                is_index = True
        
        # 根据数据类型和是否为指数选择API方法
        if is_index:
            api_methods = {
                "daily": self._pro_api.index_daily,
                "weekly": self._pro_api.index_weekly,
                "monthly": self._pro_api.index_monthly,
            }
        else:
            api_methods = {
                "daily": self._pro_api.daily,
                "weekly": self._pro_api.weekly,
                "monthly": self._pro_api.monthly,
            }
        
        if data_type not in api_methods:
            raise ValueError(f"不支持的数据类型: {data_type}")
        
        api_method = api_methods[data_type]
        
        # 执行查询
        return await self._execute_with_retry(
            lambda: api_method(
                ts_code=ts_code,
                start_date=start_date,
                end_date=end_date,
                fields=fields
            )
        )
    
    async def _execute_with_retry(self, func, *args, **kwargs):
        """
        带重试的执行函数
        
        关键改进: 使用asyncio.to_thread避免阻塞事件循环
        
        Args:
            func: 要执行的同步函数
            *args: 函数参数
            **kwargs: 函数关键字参数
        
        Returns:
            函数执行结果
        
        Raises:
            AdapterTimeoutError: 超时
            AdapterRateLimitError: 限流
            AdapterDataError: 其他错误
        """
        last_exception = None
        
        for attempt in range(self.config.retry_count):
            try:
                # 在独立线程中执行同步函数，避免阻塞事件循环
                result = await asyncio.to_thread(func, *args, **kwargs)
                return result
                
            except Exception as e:
                last_exception = e
                error_msg = str(e).lower()
                
                # 判断错误类型
                if "timeout" in error_msg:
                    last_exception = AdapterTimeoutError(f"请求超时: {e}")
                elif "rate limit" in error_msg or "频率" in error_msg:
                    last_exception = AdapterRateLimitError(f"请求限流: {e}")
                
                # 重试逻辑
                if attempt < self.config.retry_count - 1:
                    wait_time = self.config.retry_delay * (2 ** attempt)  # 指数退避
                    self.logger.warning(
                        f"第{attempt + 1}次尝试失败，{wait_time:.1f}秒后重试: {e}"
                    )
                    await asyncio.sleep(wait_time)
                else:
                    self.logger.error(f"所有重试失败: {e}")
        
        # 所有重试都失败
        if isinstance(last_exception, (AdapterTimeoutError, AdapterRateLimitError)):
            raise last_exception
        raise AdapterDataError(f"执行失败: {last_exception}")
    
    def _convert_to_bars(
        self,
        df: pd.DataFrame,
        symbol: str,
        frequency: str
    ) -> List[Bar]:
        """
        将Tushare DataFrame转换为Bar对象列表
        
        Args:
            df: Tushare返回的DataFrame
            symbol: 股票代码
            frequency: 数据频率
        
        Returns:
            List[Bar]: Bar对象列表
        """
        bars = []
        
        for _, row in df.iterrows():
            try:
                # Tushare的日期格式是YYYYMMDD字符串
                timestamp = datetime.strptime(str(row['trade_date']), '%Y%m%d')
                
                bar = Bar(
                    symbol=symbol,
                    timestamp=timestamp,
                    open=float(row['open']),
                    high=float(row['high']),
                    low=float(row['low']),
                    close=float(row['close']),
                    volume=float(row['vol']) if 'vol' in row else 0.0,
                    amount=float(row['amount']) if 'amount' in row else 0.0,
                    frequency=frequency,
                )
                bars.append(bar)
                
            except Exception as e:
                self.logger.warning(f"转换Bar失败，跳过此行: {e}")
                continue
        
        # 按时间升序排列
        bars.sort(key=lambda x: x.timestamp)
        
        return bars
    
    # ==================== 便捷方法 ====================
    
    async def get_stock_list(self, **kwargs) -> Optional[pd.DataFrame]:
        """
        获取股票列表
        
        Returns:
            Optional[pd.DataFrame]: 股票列表
        """
        if not self._connected:
            raise AdapterConnectionError("Tushare未连接")
        
        try:
            return await self._execute_with_retry(
                lambda: self._pro_api.stock_basic(
                    exchange='',
                    list_status='L',
                    fields='ts_code,symbol,name,area,industry,list_date'
                )
            )
        except Exception as e:
            raise AdapterDataError(f"获取股票列表失败: {e}")
    
    async def get_trade_calendar(
        self,
        start_date: str,
        end_date: str,
        exchange: str = 'SSE'
    ) -> Optional[pd.DataFrame]:
        """
        获取交易日历
        
        Args:
            start_date: 开始日期 (YYYYMMDD)
            end_date: 结束日期 (YYYYMMDD)
            exchange: 交易所代码
        
        Returns:
            Optional[pd.DataFrame]: 交易日历
        """
        if not self._connected:
            raise AdapterConnectionError("Tushare未连接")
        
        try:
            return await self._execute_with_retry(
                lambda: self._pro_api.trade_cal(
                    exchange=exchange,
                    start_date=start_date,
                    end_date=end_date
                )
            )
        except Exception as e:
            raise AdapterDataError(f"获取交易日历失败: {e}")
    
    # TODO: 实现能力声明系统后取消注释
    # def get_capability(self) -> AdapterCapability:
    #     """
    #     返回Tushare适配器的能力声明
    #     
    #     Returns:
    #         AdapterCapability: 能力声明对象
    #     """
    #     return AdapterCapability(
    #         name="tushare",
    #         version="1.0.0",
    #         provider="Tushare Pro",
    #         
    #         # 支持的数据类型
    #         supported_data_types={
    #             DataType.STOCK_BAR,          # 股票K线
    #             DataType.INDEX_BAR,          # 指数K线
    #             DataType.FUTURES_BAR,        # 期货K线
    #             DataType.FUND_BAR,           # 基金K线
    #             DataType.BOND_BAR,           # 债券K线
    #             DataType.OPTION_BAR,         # 期权K线
    #             DataType.FUNDAMENTAL,        # 基本面数据
    #             DataType.FINANCIAL_REPORT,   # 财务报告
    #             DataType.DIVIDEND,           # 分红送股
    #             DataType.ADJUSTMENT,         # 复权因子
    #             DataType.CALENDAR,           # 交易日历
    #         },
    #         
    #         # 支持的市场区域
    #         supported_regions={
    #             MarketRegion.CN_A,           # A股市场
    #             MarketRegion.CN_HK,          # 港股市场
    #             MarketRegion.CN_FUTURES,     # 国内期货市场
    #             MarketRegion.CN_FUND,        # 国内基金市场
    #             MarketRegion.CN_BOND,        # 国内债券市场
    #         },
    #         
    #         # 支持的数据频率
    #         supported_frequencies={
    #             "1m", "5m", "15m", "30m", "60m",  # 分钟级
    #             "1d",                               # 日线
    #             "1w",                               # 周线
    #             "1M",                               # 月线
    #         },
    #         
    #         # 特性标志
    #         features=(
    #             AdapterFeature.HISTORICAL |          # 支持历史数据
    #             AdapterFeature.BATCH_QUERY |         # 支持批量查询
    #             AdapterFeature.OFFICIAL_SOURCE |     # 官方数据源
    #             AdapterFeature.HIGH_RELIABILITY |    # 高可靠性
    #             AdapterFeature.REQUIRES_AUTH |       # 需要认证
    #             AdapterFeature.RATE_LIMITED |        # 有速率限制
    #             AdapterFeature.QUOTA_LIMITED |       # 有配额限制
    #             AdapterFeature.SUPPORTS_CACHE |      # 支持缓存
    #             AdapterFeature.SUPPORTS_RETRY        # 支持重试
    #         ),
    #         
    #         # 性能指标
    #         typical_latency_ms=300,                  # 典型延迟300ms
    #         max_qps=self.config.rate_limit_calls // (self.config.rate_limit_period // 60),  # 基于配置的QPS
    #         daily_quota=-1,                          # 取决于用户的Tushare积分
    #         
    #         # 成本信息
    #         cost_per_request=0.001,                  # 约0.001元/次（取决于积分）
    #         is_free=False,                           # 付费（需要积分）
    #         
    #         # 数据质量
    #         data_quality_score=0.95,                 # 高质量官方数据
    #         update_delay_seconds=0,                  # 历史数据无延迟
    #         
    #         # 路由配置
    #         priority=5,                              # 中等优先级
    #         weight=70,                               # 较高权重
    #         
    #         # 标签
    #         tags={"official", "china", "stock", "futures", "fund", "historical", "paid"},
    #         
    #         # 额外元数据
    #         metadata={
    #             "homepage": "https://tushare.pro",
    #             "documentation": "https://tushare.pro/document/2",
    #             "support_email": "service@tushare.org",
    #             "requires_registration": True,
    #             "pricing_model": "credit_based",
    #         }
    #     )
    
    def get_metadata(self) -> AdapterMetadata:
        """
        返回Tushare适配器的元数据
        
        Returns:
            AdapterMetadata: 元数据对象
        """
        return create_tushare_metadata()
    
    # ==================== 实时数据方法 ====================
    
    async def get_realtime_quote(
        self,
        symbols: List[str],
        source: str = "sina"
    ) -> List[Tick]:
        """
        获取实时行情快照数据
        
        使用 Tushare 的 realtime_quote 接口（纯爬虫，不需要积分）
        数据源为新浪财经，实时性高，适合获取股票和指数的实时行情
        
        Args:
            symbols: 股票或指数代码列表（支持上证/深证代码，如 000001.SH, 399001.SZ）
            source: 数据源，默认 'sina'（新浪财经）
        
        Returns:
            List[Tick]: Tick数据列表
        
        Raises:
            AdapterConnectionError: 连接失败
            AdapterDataError: 数据获取或解析失败
            AdapterTimeoutError: 请求超时
        
        示例:
            >>> ticks = await adapter.get_realtime_quote(['000001.SH', '399001.SZ'])
            >>> for tick in ticks:
            ...     print(f"{tick.symbol}: {tick.price}")
        
        注意:
            - 这是纯爬虫接口，不走 Tushare 服务器，不需要积分
            - 批量查询时最多支持50个代码
            - 交易时间外返回上一交易日收盘数据
            - 指数的买卖盘口数据通常为0
        """
        if not self._connected:
            raise AdapterConnectionError("Tushare适配器未连接，请先调用connect()")
        
        if not symbols:
            raise ValueError("symbols不能为空")
        
        if len(symbols) > 50:
            raise ValueError(f"批量查询最多支持50个代码，当前数量: {len(symbols)}")
        
        self.logger.info(f"获取实时行情: {len(symbols)} 个代码")
        
        # 执行查询（在线程池中运行，避免阻塞）
        def _fetch_realtime():
            """在同步上下文中获取实时数据（带重试机制）"""
            max_retries = 5  # 最大重试次数
            retry_delay = 1.0  # 初始延迟（秒）
            backoff_factor = 1.5  # 延迟增长倍数
            
            last_exception = None
            
            for attempt in range(max_retries):
                try:
                    # 将符号列表转换为逗号分隔的字符串
                    ts_codes = ','.join(symbols)
                    
                    # 调用 Tushare realtime_quote 接口
                    df = ts.realtime_quote(ts_code=ts_codes, src=source)
                    
                    if df is None or df.empty:
                        self.logger.warning(f"未获取到实时数据: symbols={symbols}")
                        return pd.DataFrame()
                    
                    # 成功获取数据
                    if attempt > 0:
                        self.logger.info(f"第 {attempt + 1} 次尝试成功")
                    return df
                    
                except Exception as e:
                    last_exception = e
                    error_type = type(e).__name__
                    
                    # 判断是否应该重试
                    should_retry = any([
                        'Connection' in error_type,
                        'ConnectionError' in error_type,
                        'Timeout' in error_type,
                        'SSLError' in error_type,
                        'PermissionError' in error_type,
                        'Max retries' in str(e),
                        'Connection aborted' in str(e),
                        'EOF occurred' in str(e),
                    ])
                    
                    if should_retry and attempt < max_retries - 1:
                        # 可以重试的错误
                        self.logger.warning(
                            f"第 {attempt + 1}/{max_retries} 次尝试失败 ({error_type}), "
                            f"将在 {retry_delay:.1f} 秒后重试..."
                        )
                        time.sleep(retry_delay)
                        retry_delay *= backoff_factor
                    else:
                        # 不可重试的错误或已达到最大重试次数
                        if attempt == max_retries - 1:
                            self.logger.error(f"所有 {max_retries} 次重试均失败: {error_type}: {str(e)}")
                        else:
                            self.logger.error(f"遇到不可重试的错误: {error_type}: {str(e)}")
                        raise
            
            # 如果所有重试都失败，抛出最后一个异常
            if last_exception:
                raise last_exception
            
            return pd.DataFrame()
        
        try:
            # 异步执行查询（增加超时时间以容纳重试）
            total_timeout = self.config.timeout + 30  # 额外增加30秒用于重试
            df = await asyncio.wait_for(
                asyncio.to_thread(_fetch_realtime),
                timeout=total_timeout
            )
            
            if df.empty:
                self.logger.warning("返回数据为空")
                return []
            
            # 转换为 Tick 对象
            ticks = []
            for _, row in df.iterrows():
                try:
                    # 解析时间戳
                    date_str = str(row.get('DATE', ''))
                    time_str = str(row.get('TIME', ''))
                    
                    if date_str and time_str:
                        # 合并日期和时间字符串
                        datetime_str = f"{date_str} {time_str}"
                        timestamp = pd.to_datetime(datetime_str, format='%Y%m%d %H:%M:%S')
                    else:
                        # 使用当前时间作为默认值
                        timestamp = datetime.now()
                    
                    # 创建 Tick 对象
                    tick = Tick(
                        symbol=row.get('TS_CODE', ''),
                        timestamp=timestamp,
                        price=float(row.get('PRICE', 0)),
                        volume=int(row.get('VOLUME', 0)),
                        total_amount=float(row.get('AMOUNT', 0)) if row.get('AMOUNT') else None,
                        bid_price_1=float(row.get('B1_P', 0)) if row.get('B1_P') else None,
                        ask_price_1=float(row.get('A1_P', 0)) if row.get('A1_P') else None,
                        bid_volume_1=float(row.get('B1_V', 0)) if row.get('B1_V') else None,
                        ask_volume_1=float(row.get('A1_V', 0)) if row.get('A1_V') else None,
                        # 额外字段可以放在 extra_fields 中
                        extra_fields={
                            'name': row.get('NAME', ''),
                            'open': float(row.get('OPEN', 0)),
                            'high': float(row.get('HIGH', 0)),
                            'low': float(row.get('LOW', 0)),
                            'pre_close': float(row.get('PRE_CLOSE', 0)),
                            'change': float(row.get('PRICE', 0)) - float(row.get('PRE_CLOSE', 0)),
                            'change_pct': ((float(row.get('PRICE', 0)) - float(row.get('PRE_CLOSE', 0))) / float(row.get('PRE_CLOSE', 1))) * 100 if row.get('PRE_CLOSE') and float(row.get('PRE_CLOSE', 0)) != 0 else 0,
                        }
                    )
                    ticks.append(tick)
                    
                except Exception as e:
                    self.logger.error(f"解析实时数据行失败: {e}, row={row.to_dict()}", exc_info=True)
                    continue
            
            self.logger.info(f"成功获取 {len(ticks)} 条实时数据")
            return ticks
            
        except asyncio.TimeoutError:
            error_msg = f"获取实时数据超时 (超过 {self.config.timeout}秒)"
            self.logger.error(error_msg)
            raise AdapterTimeoutError(error_msg)
            
        except Exception as e:
            error_msg = f"获取实时数据失败: {str(e)}"
            self.logger.error(error_msg, exc_info=True)
            raise AdapterDataError(error_msg) from e


# ==================== 工厂函数 ====================

def create_tushare_adapter(
    config: Dict[str, Any],
    cache_manager: Optional[Any] = None,
    logger: Optional[logging.Logger] = None
) -> TushareAdapter:
    """
    创建Tushare适配器实例（工厂函数）
    
    Args:
        config: 配置字典
        cache_manager: 可选的缓存管理器
        logger: 可选的日志记录器
    
    Returns:
        TushareAdapter: 适配器实例
    
    Example:
        ```python
        adapter = create_tushare_adapter({
            "token": "your_token_here",
            "timeout": 30,
            "retry_count": 3
        })
        ```
    """
    adapter_config = TushareAdapterConfig.from_dict(config)
    return TushareAdapter(
        config=adapter_config,
        cache_manager=cache_manager,
        logger=logger
    )